from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from django.db import transaction
from rest_framework.decorators import api_view, permission_classes, authentication_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication, SessionAuthentication
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.response import Response
from rest_framework import status
import json
import uuid
import threading
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor

from contextlib import contextmanager
from typing import Dict, List, Any, Optional

# 导入模型类
from .models import TaskStatus, TaskExecutionSummary, HistoricalData, ValidationCache, TaskContext, ProcessedDocument, ValidationResult
from dvadmin.utils.json_response import SuccessResponse, ErrorResponse

# MySQL数据库配置
DB_CONFIG = {
    "host": "rm-9yx364w4ey002550o.mysql.rds.ops.lysjfw.chnenergy.com.cn",
    "port": 3306,
    "user": "admin01",
    "password": "Clypglj!#%246",
    "database": "OCR_CER",
    "charset": "utf8mb4"
}

# 线程锁，用于确保线程安全
_db_lock = threading.Lock()

# 标记数据库是否已初始化
_db_initialized = False



def init_database():
    """
    初始化数据库表结构
    """
    global _db_initialized

    if _db_initialized:
        return



def convert_to_isoformat(time_value):
    """将时间值转换为ISO格式字符串"""
    if time_value is None:
        return None
    if isinstance(time_value, datetime):
        return time_value.isoformat()
    # 如果已经是字符串，直接返回
    if isinstance(time_value, str):
        return time_value
    # 其他类型尝试转换为datetime再转换为ISO格式
    try:
        return datetime.fromisoformat(str(time_value))
    except (ValueError, TypeError):
        return str(time_value)  # 最后的备选方案

def _row_to_dict(row) -> Dict[str, Any]:
    """
    将数据库查询结果行转换为字典
    """
    if not row:
        return {}
    
    # 假设列顺序为: id, user_id, code, if_pass, val_result, error_msg, push_time, created_time, updated_time
    return {
        'id': row[0],
        'user_id': row[1],
        'code': row[2],
        'if_pass': row[3],
        'val_result': json.loads(row[4]) if row[4] else {},
        'error_msg': json.loads(row[5]) if row[5] else [],
        'push_time': convert_to_isoformat(row[6]),
        'created_time': convert_to_isoformat(row[7]),
        'updated_time': convert_to_isoformat(row[8])
    }










# 全局任务状态管理
task_status_dict = {}
task_status_lock = threading.Lock()
task_executor = ThreadPoolExecutor(max_workers=3)

# 全局执行总结管理
execution_summary_dict = {}
execution_summary_lock = threading.Lock()

# 全局校验错误信息管理
validation_error_list = []  # 校验错误信息列表
validation_error_lock = threading.Lock()  # 校验错误信息列表的线程锁

# 任务状态常量
class TaskStatusConstants:
    PENDING = "pending"
    RUNNING = "running"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELLED = "cancelled"


def create_task(task_id, task_type, task_params):
    """创建新任务记录"""
    with task_status_lock:
        task_status_dict[task_id] = {
            "编号": task_id,
            "类型": task_type,
            "状态": TaskStatusConstants.PENDING,
            "创建时间": datetime.now().isoformat(),
            "开始时间": None,
            "完成时间": None,
            "参数": task_params,
            "结果": None,
            "错误信息": None,
            "进度": 0,
            "执行总结": None
        }


def update_task_status(task_id, status, **kwargs):
    """更新任务状态"""
    with task_status_lock:
        if task_id in task_status_dict:
            task = task_status_dict[task_id]
            if status is not None:
                task["状态"] = status

            # 根据状态自动设置时间戳
            if status == TaskStatusConstants.RUNNING and task.get("开始时间") is None:
                task["开始时间"] = datetime.now().isoformat()
            elif status in [TaskStatusConstants.COMPLETED, TaskStatusConstants.FAILED, TaskStatusConstants.CANCELLED] and task.get("完成时间") is None:
                task["完成时间"] = datetime.now().isoformat()

            # 更新其他参数
            for key, value in kwargs.items():
                task[key] = value

            # 同时更新数据库中的任务状态
            try:
                task_obj = TaskStatus.objects.get(task_id=task_id)
                task_obj.status = status
                if status == TaskStatusConstants.RUNNING and not task_obj.start_time:
                    task_obj.start_time = timezone.now()
                elif status in [TaskStatusConstants.COMPLETED, TaskStatusConstants.FAILED, TaskStatusConstants.CANCELLED] and not task_obj.end_time:
                    task_obj.end_time = timezone.now()
                
                for key, value in kwargs.items():
                    if hasattr(task_obj, key):
                        setattr(task_obj, key, value)
                
                task_obj.save()
            except TaskStatus.DoesNotExist:
                # 如果数据库中没有记录，创建新记录
                TaskStatus.objects.create(
                    task_id=task_id,
                    task_type=task.get("类型", ""),
                    status=status,
                    start_time=timezone.now() if status == TaskStatusConstants.RUNNING else None,
                    end_time=timezone.now() if status in [TaskStatusConstants.COMPLETED, TaskStatusConstants.FAILED, TaskStatusConstants.CANCELLED] else None,
                    parameters=task.get("参数", {}),
                    username=task.get("参数", {}).get("用户名", "")
                )


def get_task_status(task_id):
    """获取任务状态"""
    with task_status_lock:
        return task_status_dict.get(task_id)


def save_execution_summary(task_id, summary):
    """保存执行总结"""
    with execution_summary_lock:
        execution_summary_dict[task_id] = {
            "任务编号": task_id,
            "执行总结": summary,
            "保存时间": datetime.now().isoformat()
        }


def get_execution_summary_from_memory(task_id):
    """从内存中获取执行总结"""
    with execution_summary_lock:
        return execution_summary_dict.get(task_id)





@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_task_info(request):
    """获取任务状态"""
    try:
        task_id = request.GET.get('任务编号')
        if not task_id:
            return ErrorResponse(msg="任务编号不能为空")

        # 从内存中获取任务状态
        task_info = get_task_status(task_id)
        if not task_info:
            # 如果内存中没有，尝试从数据库获取
            try:
                task_obj = TaskStatus.objects.get(task_id=task_id)
                task_info = {
                    "编号": task_obj.task_id,
                    "类型": task_obj.task_type,
                    "状态": task_obj.status,
                    "创建时间": task_obj.create_time.isoformat() if task_obj.create_time else None,
                    "开始时间": task_obj.start_time.isoformat() if task_obj.start_time else None,
                    "完成时间": task_obj.end_time.isoformat() if task_obj.end_time else None,
                    "参数": task_obj.parameters,
                    "结果": task_obj.result,
                    "错误信息": task_obj.error_message,
                    "进度": task_obj.progress,
                    "执行总结": None
                }
            except TaskStatus.DoesNotExist:
                return ErrorResponse(msg="任务不存在")

        return SuccessResponse(data=task_info)
    except Exception as e:
        return ErrorResponse(msg=f"获取任务状态失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def task_list(request):
    """获取任务列表"""
    try:
        username = request.GET.get('用户名')
        if not username:
            return ErrorResponse(msg="用户名不能为空")

        # 从数据库获取任务列表
        tasks = TaskStatus.objects.filter(username=username).order_by('-create_time')
        
        task_list = []
        for task in tasks:
            task_info = {
                "编号": task.task_id,
                "类型": task.task_type,
                "状态": task.status,
                "创建时间": task.create_time.isoformat() if task.create_time else None,
                "开始时间": task.start_time.isoformat() if task.start_time else None,
                "完成时间": task.end_time.isoformat() if task.end_time else None,
                "进度": task.progress,
                "错误信息": task.error_message
            }
            task_list.append(task_info)

        return SuccessResponse(data={"任务列表": task_list})
    except Exception as e:
        return ErrorResponse(msg=f"获取任务列表失败: {str(e)}")


@csrf_exempt
@api_view(['POST'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def cancel_task(request):
    """取消任务"""
    try:
        data = json.loads(request.body)
        task_id = data.get('任务编号')
        if not task_id:
            return ErrorResponse(msg="任务编号不能为空")

        # 更新任务状态
        update_task_status(task_id, TaskStatusConstants.CANCELLED)

        # 更新任务上下文
        try:
            task_context = TaskContext.objects.get(task_id=task_id)
            task_context.task_running_flag = False
            task_context.save()
        except TaskContext.DoesNotExist:
            pass

        return SuccessResponse(msg="任务已取消")
    except Exception as e:
        return ErrorResponse(msg=f"取消任务失败: {str(e)}")


@csrf_exempt
@api_view(['POST'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def stop_task(request):
    """停止任务"""
    try:
        data = json.loads(request.body)
        task_id = data.get('任务编号')
        if not task_id:
            return ErrorResponse(msg="任务编号不能为空")

        # 更新任务状态
        update_task_status(task_id, TaskStatusConstants.CANCELLED)

        # 更新任务上下文
        try:
            task_context = TaskContext.objects.get(task_id=task_id)
            task_context.task_running_flag = False
            task_context.save()
        except TaskContext.DoesNotExist:
            pass

        return SuccessResponse(msg="任务已停止")
    except Exception as e:
        return ErrorResponse(msg=f"停止任务失败: {str(e)}")


@csrf_exempt
@api_view(['POST'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def submit_execution_summary(request):
    """提交执行总结"""
    try:
        data = json.loads(request.body)
        task_id = data.get('任务编号')
        summary = data.get('执行总结')
        
        if not task_id or not summary:
            return ErrorResponse(msg="任务编号和执行总结不能为空")

        # 保存执行总结到数据库
        TaskExecutionSummary.objects.update_or_create(
            task_id=task_id,
            defaults={
                'summary': summary,
                'username': request.user.username
            }
        )

        # 保存执行总结到内存
        save_execution_summary(task_id, summary)

        # 更新内存中的任务状态
        update_task_status(task_id, None, 执行总结=summary)

        return SuccessResponse(msg="执行总结已保存")
    except Exception as e:
        return ErrorResponse(msg=f"提交执行总结失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_execution_summary(request):
    """获取执行总结"""
    try:
        task_id = request.GET.get('任务编号')
        if not task_id:
            return ErrorResponse(msg="任务编号不能为空")

        # 首先从内存中获取执行总结
        summary_data = get_execution_summary_from_memory(task_id)
        
        # 如果内存中没有，从数据库获取
        if not summary_data:
            try:
                summary_obj = TaskExecutionSummary.objects.get(task_id=task_id)
                summary_data = {
                    "任务编号": summary_obj.task_id,
                    "执行总结": summary_obj.summary,
                    "创建时间": summary_obj.create_time.isoformat() if summary_obj.create_time else None,
                    "用户名": summary_obj.username
                }
            except TaskExecutionSummary.DoesNotExist:
                return ErrorResponse(msg="执行总结不存在")
        
        return SuccessResponse(data=summary_data)
    except Exception as e:
        return ErrorResponse(msg=f"获取执行总结失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_execution_summary(request):
    """获取执行总结"""
    try:
        task_id = request.GET.get('任务编号')
        if not task_id:
            return ErrorResponse(msg="任务编号不能为空")

        # 首先从内存中获取执行总结
        summary_data = get_execution_summary_from_memory(task_id)
        
        # 如果内存中没有，从数据库获取
        if not summary_data:
            try:
                summary_obj = TaskExecutionSummary.objects.get(task_id=task_id)
                summary_data = {
                    "任务编号": summary_obj.task_id,
                    "执行总结": summary_obj.summary,
                    "创建时间": summary_obj.create_time.isoformat() if summary_obj.create_time else None,
                    "用户名": summary_obj.username
                }
            except TaskExecutionSummary.DoesNotExist:
                return ErrorResponse(msg="执行总结不存在")
        
        return SuccessResponse(data=summary_data)
    except Exception as e:
        return ErrorResponse(msg=f"获取执行总结失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_execution_summary(request):
    """获取执行总结"""
    try:
        task_id = request.GET.get('任务编号')
        if not task_id:
            return ErrorResponse(msg="任务编号不能为空")

        # 首先从内存中获取执行总结
        summary_data = get_execution_summary_from_memory(task_id)
        
        # 如果内存中没有，从数据库获取
        if not summary_data:
            try:
                summary_obj = TaskExecutionSummary.objects.get(task_id=task_id)
                summary_data = {
                    "任务编号": summary_obj.task_id,
                    "执行总结": summary_obj.summary,
                    "创建时间": summary_obj.create_time.isoformat() if summary_obj.create_time else None,
                    "用户名": summary_obj.username
                }
            except TaskExecutionSummary.DoesNotExist:
                return ErrorResponse(msg="执行总结不存在")
        
        return SuccessResponse(data=summary_data)
    except Exception as e:
        return ErrorResponse(msg=f"获取执行总结失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_execution_summary(request):
    """获取执行总结"""
    try:
        task_id = request.GET.get('任务编号')
        if not task_id:
            return ErrorResponse(msg="任务编号不能为空")

        # 首先从内存中获取执行总结
        summary_data = get_execution_summary_from_memory(task_id)
        
        # 如果内存中没有，从数据库获取
        if not summary_data:
            try:
                summary_obj = TaskExecutionSummary.objects.get(task_id=task_id)
                summary_data = {
                    "任务编号": summary_obj.task_id,
                    "执行总结": summary_obj.summary,
                    "创建时间": summary_obj.create_time.isoformat() if summary_obj.create_time else None,
                    "用户名": summary_obj.username
                }
            except TaskExecutionSummary.DoesNotExist:
                return ErrorResponse(msg="执行总结不存在")
        
        return SuccessResponse(data=summary_data)
    except Exception as e:
        return ErrorResponse(msg=f"获取执行总结失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_execution_summary(request):
    """获取执行总结"""
    try:
        task_id = request.GET.get('任务编号')
        if not task_id:
            return ErrorResponse(msg="任务编号不能为空")

        # 首先从内存中获取执行总结
        summary_data = get_execution_summary_from_memory(task_id)
        
        # 如果内存中没有，从数据库获取
        if not summary_data:
            try:
                summary_obj = TaskExecutionSummary.objects.get(task_id=task_id)
                summary_data = {
                    "任务编号": summary_obj.task_id,
                    "执行总结": summary_obj.summary,
                    "创建时间": summary_obj.create_time.isoformat() if summary_obj.create_time else None,
                    "用户名": summary_obj.username
                }
            except TaskExecutionSummary.DoesNotExist:
                return ErrorResponse(msg="执行总结不存在")
        
        return SuccessResponse(data=summary_data)
    except Exception as e:
        return ErrorResponse(msg=f"获取执行总结失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_execution_summary(request):
    """获取执行总结"""
    try:
        task_id = request.GET.get('任务编号')
        if not task_id:
            return ErrorResponse(msg="任务编号不能为空")

        # 首先从内存中获取执行总结
        summary_data = get_execution_summary_from_memory(task_id)
        
        # 如果内存中没有，从数据库获取
        if not summary_data:
            try:
                summary_obj = TaskExecutionSummary.objects.get(task_id=task_id)
                summary_data = {
                    "任务编号": summary_obj.task_id,
                    "执行总结": summary_obj.summary,
                    "创建时间": summary_obj.create_time.isoformat() if summary_obj.create_time else None,
                    "用户名": summary_obj.username
                }
            except TaskExecutionSummary.DoesNotExist:
                return ErrorResponse(msg="执行总结不存在")
        
        return SuccessResponse(data=summary_data)
    except Exception as e:
        return ErrorResponse(msg=f"获取执行总结失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_execution_summary(request):
    """获取执行总结"""
    try:
        task_id = request.GET.get('任务编号')
        if not task_id:
            return ErrorResponse(msg="任务编号不能为空")

        # 首先从内存中获取执行总结
        summary_data = get_execution_summary_from_memory(task_id)
        
        # 如果内存中没有，从数据库获取
        if not summary_data:
            try:
                summary_obj = TaskExecutionSummary.objects.get(task_id=task_id)
                summary_data = {
                    "任务编号": summary_obj.task_id,
                    "执行总结": summary_obj.summary,
                    "创建时间": summary_obj.create_time.isoformat() if summary_obj.create_time else None,
                    "用户名": summary_obj.username
                }
            except TaskExecutionSummary.DoesNotExist:
                return ErrorResponse(msg="执行总结不存在")
        
        return SuccessResponse(data=summary_data)
    except Exception as e:
        return ErrorResponse(msg=f"获取执行总结失败: {str(e)}")


@csrf_exempt
@api_view(['POST'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def push_validation_result(request):
    """
    推送校验结果接口
    
    功能:
        接收OCR程序推送的校验结果，并存储到MySQL数据库中
    
    请求体:
        JSON格式，包含单据号、校验结果等信息
    
    返回:
        操作结果的JSON响应
    """
    try:
        data = json.loads(request.body)
        if not data:
            return ErrorResponse(msg="请求体不能为空")
        
        # 验证必需参数
        if '单据号' not in data:
            return ErrorResponse(msg="缺少必需参数: 单据号")
        
        document_number = data['单据号']
        validation_result = data.get('校验结果', {})
        detailed_error_info = data.get('详细错误信息', [])  # 获取详细错误信息
        push_time = data.get('推送时间', datetime.now().isoformat())
        
        # 解析任务编号，兼容多种字段名
        task_id = (
            data.get('任务编号') or data.get('task_id') or data.get('taskId')
        )
        
        # 获取用户名字段
        username = data.get('用户名') or data.get('user_name') or data.get('username')
        
        # 存储校验结果到执行总结字典（内存缓存）
        with execution_summary_lock:
            execution_summary_dict[document_number] = {
                "单据号": document_number,
                "校验结果": validation_result,
                "详细错误信息": detailed_error_info,  # 保存详细错误信息
                "推送时间": push_time,
                "类型": "校验结果推送",
                "状态": "已推送",
                "用户名": username,
                "任务编号": task_id,
            }
        
        # 同时保存到Django数据库
        try:
            ProcessedDocument.objects.update_or_create(
                document_number=document_number,
                defaults={
                    'validation_result': validation_result,
                    'detailed_error_info': detailed_error_info,
                    'push_time': push_time,
                    'type': '校验结果推送',
                    'status': '已推送',
                    'username': username,
                    'task_id': task_id,
                }
            )
        except Exception as db_error:
            print(f"保存校验结果到Django数据库失败: {db_error}")
        
        # 保存到ValidationResult表
        try:
            # 判断是否通过校验
            if_pass = validation_result.get('if_pass', False)
            
            # 解析推送时间
            if isinstance(push_time, str):
                push_time = datetime.fromisoformat(push_time.replace('Z', '+00:00'))
            
            # 使用update_or_create处理重复记录
            ValidationResult.objects.update_or_create(
                user_id=username,
                code=document_number,
                defaults={
                    'val_result': validation_result.get('val_result', False),
                    'error_msg': detailed_error_info,
                    'if_pass': if_pass,
                    'push_time': push_time,
                }
            )
            
            print(f"成功保存校验结果到ValidationResult表: {document_number}")
                
        except Exception as validation_error:
            print(f"保存校验结果到ValidationResult表失败: {validation_error}")
        
        print(f"成功接收校验结果推送: {document_number}，包含 {len(detailed_error_info)} 条详细错误信息")
        
        return SuccessResponse(
            data={
                "单据号": document_number,
                "时间戳": datetime.now().isoformat()
            },
            message=f"校验结果已接收: {document_number}"
        )
        
    except Exception as e:
        print(f"推送校验结果失败: {e}")
        return ErrorResponse(msg=f"推送校验结果失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_error_logs(request):
    """
    获取错误日志接口
    
    功能:
        返回系统收集的校验错误日志信息
    
    返回:
        包含错误日志列表的JSON响应
    """
    try:
        # 获取校验错误信息列表
        error_log_list = []
        with validation_error_lock:
            for error_info in validation_error_list:
                error_log_list.append({
                    "时间": datetime.now().isoformat(),
                    "类型": "校验错误",
                    "错误信息": error_info,
                    "详细信息": error_info
                })
        
        return SuccessResponse(
            data={
                "错误日志": error_log_list,
                "总数量": len(error_log_list),
                "时间戳": datetime.now().isoformat()
            },
            message="获取错误日志成功"
        )
        
    except Exception as e:
        print(f"获取错误日志失败: {e}")
        return ErrorResponse(msg=f"获取错误日志失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_validation_error_summary(request):
    """
    获取校验错误总结接口
    
    功能:
        返回校验未通过项目的总结信息
    
    参数:
        单据号 (可选): URL参数，如果不提供则使用"未知单据"
    
    返回:
        包含校验错误总结的JSON响应
    """
    try:
        # 从请求参数中获取单据号，如果没有提供则使用默认值
        document_number = request.GET.get('单据号', '未知单据')
        
        # 获取校验错误信息列表
        error_list = []
        with validation_error_lock:
            error_list = list(validation_error_list)
        
        # 调用总结函数，传入单据号参数
        validation_summary = summarize_validation_failed_items(document_number, error_list)
        
        return SuccessResponse(
            data={
                "单据号": document_number,
                "校验总结": validation_summary,
                "校验错误列表": error_list,
                "时间戳": datetime.now().isoformat()
            },
            message="获取校验错误总结成功"
        )
        
    except Exception as e:
        return ErrorResponse(msg=f"获取校验错误总结失败: {str(e)}")


def summarize_validation_failed_items(document_number, error_list):
    """
    总结校验未通过项目
    
    参数:
        document_number: 单据号
        error_list: 错误信息列表
    
    返回:
        校验总结信息
    """
    try:
        # 这里实现校验未通过项目的总结逻辑
        # 可以根据实际需求进行修改
        
        summary = {
            "单据号": document_number,
            "总错误数": len(error_list),
            "错误类型统计": {},
            "主要错误": [],
            "建议操作": []
        }
        
        # 统计错误类型
        for error in error_list:
            error_type = "通用错误"  # 默认错误类型
            if isinstance(error, dict) and "type" in error:
                error_type = error["type"]
            elif isinstance(error, str):
                # 尝试从错误信息中提取错误类型
                if "字段" in error:
                    error_type = "字段错误"
                elif "格式" in error:
                    error_type = "格式错误"
                elif "必填" in error:
                    error_type = "必填项错误"
            
            if error_type not in summary["错误类型统计"]:
                summary["错误类型统计"][error_type] = 0
            summary["错误类型统计"][error_type] += 1
        
        # 提取主要错误（前5个）
        summary["主要错误"] = error_list[:5]
        
        # 根据错误类型提供建议操作
        if "字段错误" in summary["错误类型统计"]:
            summary["建议操作"].append("检查字段名称和拼写是否正确")
        if "格式错误" in summary["错误类型统计"]:
            summary["建议操作"].append("确保数据格式符合要求")
        if "必填项错误" in summary["错误类型统计"]:
            summary["建议操作"].append("填写所有必填项")
        
        if not summary["建议操作"]:
            summary["建议操作"].append("请仔细检查所有数据并重新提交")
        
        return summary
        
    except Exception as e:
        return {
            "单据号": document_number,
            "错误": f"总结校验未通过项目失败: {str(e)}"
        }





# ==================== 历史数据管理功能 ====================

# 全局缓存字典，用于存储用户校验结果缓存
user_cache_instances = {}
user_cache_lock = threading.Lock()

def get_user_cache(username):
    """获取用户的缓存实例"""
    with user_cache_lock:
        if username not in user_cache_instances:
            user_cache_instances[username] = {}
        return user_cache_instances[username]


def get_validation_result(username, document_number):
    """获取指定单据号的校验结果"""
    # 首先从缓存中查找
    user_cache = get_user_cache(username)
    if document_number in user_cache:
        return user_cache[document_number]
    
    # 缓存中没有，从数据库中查找
    try:
        doc = ProcessedDocument.objects.filter(
            username=username,
            document_number=document_number
        ).first()
        
        if doc:
            result = {
                "单据号": doc.document_number,
                "处理结果": doc.processing_result,
                "处理时间": doc.processing_time.isoformat() if doc.processing_time else None,
                "校验结果": doc.validation_result,
                "错误信息": doc.error_message,
                "处理状态": doc.processing_status
            }
            # 将结果存入缓存
            user_cache[document_number] = result
            return result
    except Exception as e:
        print(f"获取校验结果失败: {str(e)}")
    
    return None


def get_all_validation_results(username, limit=None, offset=None):
    """获取用户的所有校验结果"""
    try:
        # 从数据库获取所有处理过的文档
        docs = ProcessedDocument.objects.filter(username=username)
        
        # 应用分页
        if offset is not None:
            docs = docs[offset:]
        if limit is not None:
            docs = docs[:limit]
            
        results = []
        for doc in docs:
            result = {
                "单据号": doc.document_number,
                "处理结果": doc.processing_result,
                "处理时间": doc.processing_time.isoformat() if doc.processing_time else None,
                "校验结果": doc.validation_result,
                "错误信息": doc.error_message,
                "处理状态": doc.processing_status
            }
            results.append(result)
            
        return results
    except Exception as e:
        print(f"获取所有校验结果失败: {str(e)}")
        return []


def get_validation_results_by_time_range(username, start_time, end_time):
    """根据时间范围获取校验结果"""
    try:
        # 将字符串时间转换为datetime对象
        start_dt = datetime.fromisoformat(start_time.replace('Z', '+00:00'))
        end_dt = datetime.fromisoformat(end_time.replace('Z', '+00:00'))
        
        # 从数据库获取指定时间范围内的文档
        docs = ProcessedDocument.objects.filter(
            username=username,
            processing_time__gte=start_dt,
            processing_time__lte=end_dt
        )
            
        results = []
        for doc in docs:
            result = {
                "单据号": doc.document_number,
                "处理结果": doc.processing_result,
                "处理时间": doc.processing_time.isoformat() if doc.processing_time else None,
                "校验结果": doc.validation_result,
                "错误信息": doc.error_message,
                "处理状态": doc.processing_status
            }
            results.append(result)
            
        return results
    except Exception as e:
        print(f"根据时间范围获取校验结果失败: {str(e)}")
        return []


def get_cache_stats(username):
    """获取缓存统计信息"""
    user_cache = get_user_cache(username)
    return {
        "缓存条目数": len(user_cache),
        "用户名": username
    }


def delete_validation_result(username, document_number):
    """删除指定单据号的校验结果"""
    try:
        # 从缓存中删除
        user_cache = get_user_cache(username)
        if document_number in user_cache:
            del user_cache[document_number]
        
        # 从数据库中删除
        deleted_count, _ = ProcessedDocument.objects.filter(
            username=username,
            document_number=document_number
        ).delete()
        
        return deleted_count > 0
    except Exception as e:
        print(f"删除校验结果失败: {str(e)}")
        return False


def cleanup_old_results(username, days=30):
    """清理指定天数前的旧结果"""
    try:
        # 计算截止日期
        cutoff_date = datetime.now() - timezone.timedelta(days=days)
        
        # 从数据库中删除旧记录
        deleted_count, _ = ProcessedDocument.objects.filter(
            username=username,
            processing_time__lt=cutoff_date
        ).delete()
        
        # 清理缓存中的旧记录（这里简化处理，直接清空缓存）
        user_cache = get_user_cache(username)
        user_cache.clear()
        
        return deleted_count
    except Exception as e:
        print(f"清理旧结果失败: {str(e)}")
        return 0


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_push_result(request):
    """获取推送结果（按单据号查询）"""
    try:
        username = request.GET.get('用户名')
        document_number = request.GET.get('单据号')
        
        if not username or not document_number:
            return ErrorResponse(msg="用户名和单据号不能为空")
        
        result = get_validation_result(username, document_number)
        
        if result:
            return SuccessResponse(data=result)
        else:
            return ErrorResponse(msg="未找到指定的推送结果")
    except Exception as e:
        return ErrorResponse(msg=f"获取推送结果失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_all_push_results(request):
    """获取所有推送结果（合并缓存和数据库数据）"""
    try:
        username = request.GET.get('用户名')
        if not username:
            return ErrorResponse(msg="用户名不能为空")
        
        # 获取缓存统计
        cache_stats = get_cache_stats(username)
        
        # 获取所有结果
        limit = request.GET.get('限制')
        offset = request.GET.get('偏移')
        
        # 转换为整数
        if limit is not None:
            try:
                limit = int(limit)
            except ValueError:
                limit = None
        if offset is not None:
            try:
                offset = int(offset)
            except ValueError:
                offset = None
                
        results = get_all_validation_results(username, limit, offset)
        
        response_data = {
            "缓存统计": cache_stats,
            "结果列表": results
        }
        
        return SuccessResponse(data=response_data)
    except Exception as e:
        return ErrorResponse(msg=f"获取所有推送结果失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_history(request):
    """
    获取校验结果历史记录
    
    功能:
        从ValidationResult表中获取校验结果的历史记录，支持分页和筛选
    
    参数:
        page: 页码，默认为1
        limit: 每页记录数，默认为10（也支持 size 参数）
        user_id: 用户ID筛选，可选
        document_id: 单据号筛选，可选
        start_date: 开始日期，格式为YYYY-MM-DD，可选
        end_date: 结束日期，格式为YYYY-MM-DD，可选
        if_pass: 是否通过校验，可选，值为true/false
    
    返回:
        分页的校验结果历史记录
    """
    try:
        # 获取查询参数
        page = int(request.GET.get('page', 1))
        # 支持 limit 和 size 两种参数名
        size = int(request.GET.get('limit', request.GET.get('size', 10)))
        user_id = request.GET.get('user_id')
        start_date = request.GET.get('start_date')
        end_date = request.GET.get('end_date')
        if_pass = request.GET.get('if_pass')
        document_id = request.GET.get('document_id')  # 单据号查询参数
        
        # 构建查询条件
        queryset = ValidationResult.objects.all()
        
        if user_id:
            # 支持多个user_id，用逗号分隔，如：user_id=1,2,3
            user_id_list = [uid.strip() for uid in user_id.split(',') if uid.strip()]
            if user_id_list:
                queryset = queryset.filter(user_id__in=user_id_list)
        
        # 单据号查询（code 字段）- 支持部分匹配
        if document_id:
            queryset = queryset.filter(code__icontains=document_id)
        
        if start_date:
            queryset = queryset.filter(push_time__gte=start_date)
        
        if end_date:
            queryset = queryset.filter(push_time__lte=end_date + " 23:59:59")
        
        if if_pass is not None:
            queryset = queryset.filter(if_pass=if_pass.lower() == 'true')
        
        # 按推送时间倒序排序
        queryset = queryset.order_by('-push_time')
        
        # 获取总记录数
        total_count = queryset.count()
        
        # 应用分页
        offset = (page - 1) * size
        results = queryset[offset:offset + size]
        
        # 格式化结果
        formatted_results = []
        for result in results:
            formatted_results.append({
                "id": result.id,
                "user_id": result.user_id,
                "code": result.code,
                "document_id": result.code,  # 添加 document_id 字段以保持兼容性
                "val_result": result.val_result,
                "error_msg": result.error_msg,
                "pass_flag": result.if_pass,
                "if_pass": result.if_pass,  # 添加 if_pass 字段以保持兼容性
                "push_time": result.push_time.isoformat() if result.push_time else None,
                "created_time": result.created_time.isoformat() if result.created_time else None,
                "updated_time": result.updated_time.isoformat() if result.updated_time else None,
            })
        
        # 计算总页数
        total_pages = (total_count + size - 1) // size
        
        return SuccessResponse(
            data={
                "results": formatted_results,
                "pagination": {
                    "page": page,
                    "size": size,
                    "total_count": total_count,
                    "total_pages": total_pages
                }
            },
            msg="获取历史记录成功"
        )
        
    except Exception as e:
        print(f"获取历史记录失败: {e}")
        return ErrorResponse(msg=f"获取历史记录失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def query_history_data(request):
    """
    查询历史数据
    
    功能:
        从ValidationResult表中查询历史数据，支持按时间范围查询
    
    参数:
        start_date: 开始日期，格式为YYYY-MM-DD，可选
        end_date: 结束日期，格式为YYYY-MM-DD，可选
        user_id: 用户ID筛选，可选
        if_pass: 是否通过校验，可选，值为true/false
    
    返回:
        查询结果列表
    """
    try:
        # 获取查询参数
        start_date = request.GET.get('start_date')
        end_date = request.GET.get('end_date')
        user_id = request.GET.get('user_id')
        if_pass = request.GET.get('if_pass')
        
        # 构建查询条件
        queryset = ValidationResult.objects.all()
        
        if user_id:
            # 支持多个user_id，用逗号分隔，如：user_id=1,2,3
            user_id_list = [uid.strip() for uid in user_id.split(',') if uid.strip()]
            if user_id_list:
                queryset = queryset.filter(user_id__in=user_id_list)
        
        if start_date:
            queryset = queryset.filter(push_time__gte=start_date)
        
        if end_date:
            queryset = queryset.filter(push_time__lte=end_date + " 23:59:59")
        
        if if_pass is not None:
            queryset = queryset.filter(if_pass=if_pass.lower() == 'true')
        
        # 只查询需要的字段，优化查询性能
        queryset = queryset.only('id', 'push_time', 'if_pass', 'code')
        
        # 按推送时间倒序排序
        queryset = queryset.order_by('-push_time')
        
        # 格式化结果
        results = []
        for result in queryset:
            results.append({
                "id": result.id,
                "code": result.code,
                "document_id": result.code,  # 添加 document_id 字段以保持兼容性
                "pass_flag": result.if_pass,
                "if_pass": result.if_pass,
                "push_time": result.push_time.isoformat() if result.push_time else None,
            })
        
        return SuccessResponse(
            data=results,
            msg="查询历史数据成功"
        )
        
    except Exception as e:
        print(f"查询历史数据失败: {e}")
        return ErrorResponse(msg=f"查询历史数据失败: {str(e)}")


@csrf_exempt
@api_view(['DELETE'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def delete_history_data(request):
    """
    删除历史数据
    
    功能:
        从ValidationResult表中删除指定的历史数据
    
    参数:
        id: 要删除的记录ID，必填
    
    返回:
        删除结果
    """
    try:
        # 获取要删除的记录ID
        record_id = request.GET.get('id')
        if not record_id:
            return ErrorResponse(msg="记录ID不能为空")
        
        # 删除记录
        deleted_count, _ = ValidationResult.objects.filter(id=record_id).delete()
        
        if deleted_count > 0:
            return SuccessResponse(msg="删除历史数据成功")
        else:
            return ErrorResponse(msg="删除历史数据失败，记录不存在")
            
    except Exception as e:
        print(f"删除历史数据失败: {e}")
        return ErrorResponse(msg=f"删除历史数据失败: {str(e)}")


@csrf_exempt
@api_view(['POST'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def batch_delete_history_data(request):
    """
    批量删除历史数据
    
    功能:
        从ValidationResult表中批量删除指定的历史数据
    
    参数:
        ids: 要删除的记录ID列表，多个ID用逗号分隔，必填
    
    返回:
        删除结果
    """
    try:
        # 获取要删除的记录ID列表
        ids = request.GET.get('ids')
        if not ids:
            return ErrorResponse(msg="记录ID列表不能为空")
        
        # 分割ID字符串
        id_list = ids.split(',')
        id_list = [id.strip() for id in id_list if id.strip()]
        
        if not id_list:
            return ErrorResponse(msg="没有有效的记录ID")
        
        # 批量删除记录
        deleted_count, _ = ValidationResult.objects.filter(id__in=id_list).delete()
        
        return SuccessResponse(
            data={
                "total": len(id_list),
                "success": deleted_count,
                "failed": len(id_list) - deleted_count
            },
            message=f"批量删除完成，成功删除 {deleted_count} 条记录"
        )
            
    except Exception as e:
        print(f"批量删除历史数据失败: {e}")
        return ErrorResponse(msg=f"批量删除历史数据失败: {str(e)}")


@csrf_exempt
@api_view(['POST'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def cleanup_history_data(request):
    """
    清理历史数据
    
    功能:
        从ValidationResult表中清理指定时间之前的历史数据
    
    参数:
        days: 要保留的天数，默认为30天，可选
    
    返回:
        清理结果
    """
    try:
        # 获取要保留的天数
        days = int(request.GET.get('days', 30))
        
        # 计算截止日期
        cutoff_date = timezone.now() - timezone.timedelta(days=days)
        
        # 删除指定时间之前的记录
        deleted_count, _ = ValidationResult.objects.filter(push_time__lt=cutoff_date).delete()
        
        return SuccessResponse(
            data={
                "deleted_count": deleted_count,
                "cutoff_date": cutoff_date.isoformat(),
                "retention_days": days
            },
            message=f"清理完成，删除了 {deleted_count} 条 {days} 天前的历史数据"
        )
            
    except Exception as e:
        print(f"清理历史数据失败: {e}")
        return ErrorResponse(msg=f"清理历史数据失败: {str(e)}")


@csrf_exempt
@api_view(['GET'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def get_history_stats(request):
    """
    获取历史数据统计
    
    功能:
        从ValidationResult表中获取历史数据的统计信息
    
    参数:
        user_id: 用户ID，可选，不提供则统计所有用户的数据
        days: 统计天数，默认为7天，可选
    
    返回:
        统计结果
    """
    try:
        # 获取参数
        user_id = request.GET.get('user_id')
        days = int(request.GET.get('days', 7))
        
        # 计算起始日期
        start_date = timezone.now() - timezone.timedelta(days=days)
        
        # 构建查询条件
        queryset = ValidationResult.objects.filter(push_time__gte=start_date)
        if user_id:
            queryset = queryset.filter(user_id=user_id)
        
        # 统计数据
        total_count = queryset.count()
        passed_count = queryset.filter(if_pass=True).count()
        failed_count = total_count - passed_count
        
        # 按日期统计
        daily_stats = []
        for i in range(days):
            date = (timezone.now() - timezone.timedelta(days=i)).date()
            day_queryset = queryset.filter(push_time__date=date)
            day_total = day_queryset.count()
            day_passed = day_queryset.filter(if_pass=True).count()
            day_failed = day_total - day_passed
            
            daily_stats.append({
                "date": date.isoformat(),
                "total": day_total,
                "passed": day_passed,
                "failed": day_failed
            })
        
        # 反转日期列表，使最早的日期在前
        daily_stats.reverse()
        
        return SuccessResponse(
            data={
                "total_count": total_count,
                "passed_count": passed_count,
                "failed_count": failed_count,
                "pass_rate": f"{(passed_count / total_count * 100):.2f}%" if total_count > 0 else "0%",
                "days": days,
                "user_id": user_id,
                "daily_stats": daily_stats
            },
            message="统计信息获取成功"
        )
            
    except Exception as e:
        print(f"获取历史数据统计失败: {e}")
        return ErrorResponse(msg=f"获取历史数据统计失败: {str(e)}")